package com.virgo.demo.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.virgo.common.entity.ListDataVo;
import com.virgo.common.exception.IApplicationException;
import com.virgo.common.utils.ICommonUtils;
import com.virgo.common.utils.ITimeUtils;
import com.virgo.common.utils.IUserUtils;
import com.virgo.common.utils.IValidateUtils;
import com.virgo.demo.core.consts.SiteConst;
import com.virgo.demo.system.converter.AdminUserConverter;
import com.virgo.demo.system.domain.AdminRoleDo;
import com.virgo.demo.system.domain.AdminUserDo;
import com.virgo.demo.system.domain.bo.AdminUserBo;
import com.virgo.demo.system.domain.vo.AdminUserVo;
import com.virgo.demo.system.mapper.AdminRoleMapper;
import com.virgo.demo.system.mapper.AdminUserMapper;
import com.virgo.demo.system.service.AdminUserService;
import com.virgo.login.service.TokenService;
import com.virgo.web.utils.IRequestUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;

@Service
@RequiredArgsConstructor
public class AdminUserServiceImpl extends ServiceImpl<AdminUserMapper, AdminUserDo> implements AdminUserService {

	private final AdminUserConverter adminUserConverter;

	private final AdminUserMapper adminUserMapper;

	private final TokenService tokenService;

    private final AdminRoleMapper adminRoleMapper;

    private final ThreadPoolTaskExecutor threadPoolTaskExecutor;

	@Override
	public AdminUserDo loadByAdminName(String adminName) {
		LambdaQueryWrapper<AdminUserDo> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(AdminUserDo::getAdminName,adminName);
		queryWrapper.last(" limit 1 ");
		return getOne(queryWrapper);
	}

	/**
	 * 登录后的记录
	 * @param adminUserDo AdminUserDo
	 */
	@Override
	@Async
	public void doLoginAfter(AdminUserDo adminUserDo, String ip) {
		UpdateWrapper<AdminUserDo> updateWrapper = new UpdateWrapper<>();
		updateWrapper.eq("id",adminUserDo.getId());
		updateWrapper.set("last_login_at", ITimeUtils.gmTime());
		updateWrapper.set("last_login_ip", ip);
		updateWrapper.setSql(" login_num=login_num+1 ");
		update(updateWrapper);
	}

	/**
	 * 编辑管理员
	 * @param adminUserBo AdminUserBo
	 */
	@Override
	public void saveAdminUser(AdminUserBo adminUserBo) {
		AdminUserDo exist = loadByAdminName(adminUserBo.getAdminName());
		AdminUserDo adminUserDo = new AdminUserDo();
		BeanUtils.copyProperties(adminUserBo,adminUserDo);
		if (!ObjectUtils.isEmpty(exist) && !exist.getId().equals(adminUserDo.getId())) {
			throw new IApplicationException("账号-" + adminUserDo.getAdminName() + "已存在");
		}
		if (ObjectUtils.isEmpty(adminUserDo.getId()) || adminUserDo.getId().compareTo(0L) < 1) {
			//新增
			if (!IValidateUtils.password(adminUserBo.getPassword())) {
				throw new IApplicationException("密码格式错误");
			}
			adminUserDo.setPwdSalt(IUserUtils.createSalt(SiteConst.AdminUserType));
			adminUserDo.setLoginPwd(IUserUtils.encodePassWord(adminUserBo.getPassword(),adminUserDo.getPwdSalt()));
			save(adminUserDo);
			return;
		}
		if (!ObjectUtils.isEmpty(adminUserBo.getPassword())) {
			//传了密码才校验
			if (!IValidateUtils.password(adminUserBo.getPassword())) {
				throw new IApplicationException("密码格式错误");
			}
			AdminUserDo user = getById(adminUserDo.getId());
			if (ObjectUtils.isEmpty(user)) {
				throw new IApplicationException("修改数据不存在");
			}
			adminUserDo.setLoginPwd(IUserUtils.encodePassWord(adminUserBo.getPassword(),user.getPwdSalt()));
			//这个人退出登录
			tokenService.delete(SiteConst.AdminUserType, user.getId());
		}
		updateById(adminUserDo);
	}

	/**
	 * 删除用户
	 * @param ids String
	 */
	@Override
	public void deleteUser(String ids) {
		List<Long> idList = Arrays.asList(ICommonUtils.stringToArray(ids, ","));
		removeByIds(idList);
	}

	/**
	 * 修改状态
	 * @param id     Long
	 * @param status Long
	 */
	@Override
	public void updateStatus(Long id, Integer status) {
		AdminUserDo adminUserDo = new AdminUserDo();
		adminUserDo.setId(id);
		adminUserDo.setStatus(status);
		updateById(adminUserDo);
		tokenService.delete(SiteConst.AdminUserType, id);
	}

	/**
	 * 重制登录密码
	 * @param id       Long
	 * @param password String
	 */
	@Override
	public void resetPassword(Long id, String password) {
		AdminUserDo user = getById(id);
		if (ObjectUtils.isEmpty(user)) {
			throw new IApplicationException("用户不存在");
		}
		password = IUserUtils.encodePassWord(password,user.getPwdSalt());
		AdminUserDo adminUserDo = new AdminUserDo();
		adminUserDo.setId(id);
		adminUserDo.setLoginPwd(password);
		updateById(adminUserDo);
		tokenService.delete(SiteConst.AdminUserType, id);
	}

	/**
	 * 管理员列表
	 * @param request HttpServletRequest
	 * @return ListDataVo<AdminUserVo>
	 */
	@Override
	public ListDataVo<AdminUserVo> findList(HttpServletRequest request) {
		long currentPage = IRequestUtils.getLong(request,"page");
		long pageSize = IRequestUtils.getLong(request,"pageSize");
		currentPage = Math.max(currentPage,1);
		pageSize = Math.max(pageSize,10);

		LambdaQueryWrapper<AdminUserDo> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.gt(AdminUserDo::getRoleId,0L);
		queryWrapper.orderByDesc(AdminUserDo::getId);

		String adminName = IRequestUtils.getString(request,"adminName","");
		if (!ObjectUtils.isEmpty(adminName)) {
			queryWrapper.like(AdminUserDo::getAdminName,adminName);
		}

		String nickName = IRequestUtils.getString(request,"nickName","");
		if (!ObjectUtils.isEmpty(nickName)) {
			queryWrapper.like(AdminUserDo::getNickName,nickName);
		}

		String status = IRequestUtils.getString(request,"status","");
		if ("1".equals(status)) {
			queryWrapper.eq(AdminUserDo::getStatus,1);
		} else if ("0".equals(status)) {
			queryWrapper.eq(AdminUserDo::getStatus,0);
		}
		Page<AdminUserDo> page = new Page<>(currentPage, pageSize);
		IPage<AdminUserDo> iPage = adminUserMapper.selectPage(page, queryWrapper);
        List<AdminUserVo> adminUserVos = adminUserConverter.convert(iPage.getRecords(), AdminUserVo.class);
        ArrayList<CompletableFuture<Void>> futureList = new ArrayList<>();
        for (AdminUserVo adminUserVo : adminUserVos) {
            CompletableFuture<Void> userInfoFuture = CompletableFuture.runAsync(() -> {
                adminUserVo.setRoleName("");
                LambdaQueryWrapper<AdminRoleDo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                lambdaQueryWrapper.eq(AdminRoleDo::getId,adminUserVo.getRoleId());
                lambdaQueryWrapper.select(AdminRoleDo::getName);
                lambdaQueryWrapper.last(" limit 1 ");
                AdminRoleDo adminRoleDo = adminRoleMapper.selectOne(lambdaQueryWrapper);
                if (!ObjectUtils.isEmpty(adminRoleDo)) {
                    adminUserVo.setRoleName(adminRoleDo.getName());
                }
             },threadPoolTaskExecutor);
            futureList.add(userInfoFuture);
        }
        CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).join();
        return new ListDataVo<>(iPage.getTotal(),iPage.getPages(),adminUserVos);
	}
}